package com.quanyan.travel.service.impl;

import com.alibaba.rocketmq.common.message.MessageExt;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.quanyan.api.APIRequest;
import com.quanyan.api.APIResponse;
import com.quanyan.api.enums.AssetsPayReceive;
import com.quanyan.api.enums.AssetsType;
import com.quanyan.assets.request.ReqRuleDetail;
import com.quanyan.assets.request.ReqUserAccumulateModify;
import com.quanyan.assets.response.RespRuleDetail;
import com.quanyan.assets.response.RespUserAccumulateModify;
import com.quanyan.assets.service.UserAssetsService;
import com.quanyan.comment.constants.UserCenterConstants;
import com.quanyan.comment.reqeust.ReqCommentParam;
import com.quanyan.comment.serviceFacade.CommentServiceFacade;
import com.quanyan.common.Plugin.PageObj;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.utils.DateUtils;
import com.quanyan.common.utils.ObjectUtil;
import com.quanyan.orderpay.request.*;
import com.quanyan.orderpay.response.RespPayInfo;
import com.quanyan.orderpay.response.RespPreOrder;
import com.quanyan.orderpay.response.mq.OrderNotifyMsg;
import com.quanyan.orderpay.response.mq.RefundNotifyMsg;
import com.quanyan.orderpay.service.OrderPayService;
import com.quanyan.pay.enums.PayWayEnum;
import com.quanyan.pay.enums.RefundStatusEnum;
import com.quanyan.travel.api.req.ReqAccess;
import com.quanyan.travel.api.req.ReqOrderConfirmMsg;
import com.quanyan.travel.api.req.ReqOrderMsg;
import com.quanyan.travel.api.req.ReqSignUser;
import com.quanyan.travel.api.resp.*;
import com.quanyan.travel.biz.BizTravelOrderService;
import com.quanyan.travel.component.asyn.TravelAsyncService;
import com.quanyan.travel.constants.OutdoorConstants;
import com.quanyan.travel.entity.*;
import com.quanyan.travel.entity.vo.*;
import com.quanyan.travel.enums.ErrorEnum;
import com.quanyan.travel.enums.RefundMsgEnum;
import com.quanyan.travel.service.TravelBaseService;
import com.quanyan.travel.service.TravelCacheService;
import com.quanyan.travel.service.TravelMsgService;
import com.quanyan.travel.service.TravelOrderService;
import com.quanyan.travel.utils.OrderUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

/**
 * 订单Service
 * Created by yangyun on 2016/4/19.
 */


@Service("travelOrderService")
public class TravelOrderServiceImpl implements TravelOrderService {

    private static Logger logger = LoggerFactory.getLogger(TravelOrderServiceImpl.class);

    @Autowired
    private BizTravelOrderService bizTravelOrderService;

    @Autowired
    private CommentServiceFacade commentServiceFacade;

    @Autowired
    private UserAssetsService userAssetsService;

    @Autowired
    private OrderPayService orderPayService;

    @Autowired
    private TravelAsyncService travelAsyncService;

    @Autowired
    private TravelBaseService travelBaseService;

    @Autowired
    private TravelMsgService travelMsgService;

    @Autowired
    private TravelCacheService travelCacheService;

    @Value("${notify.url.payUrl}")
    private String payUrl;

    @Value("${notify.url.refundUrl}")
    private String refundUrl;

    @Value("${notify.url.closeOrderUrl}")
    private String closeOrderUrl;

    @Value("${notify.url.exceptionOrderUrl}")
    private String exceptionOrderUrl;

    @Override
    public APIResponse<RespActivitySignInfo> userSign(Integer uid, ReqSignUser reqSignUser) {
        if (1==1) {
            return APIResponse.returnFail("该业务已下线");
        }
        RespActivitySignInfo respActivitySignInfo = new RespActivitySignInfo();
        List<ProductDetail> productList = bizTravelOrderService.queryProductDetailByIds(reqSignUser.getProductIds());
        if (null == productList || productList.size() == 0) {
            return APIResponse.returnFail(ErrorEnum.ERROR_PARAM.getId(), ErrorEnum.ERROR_PARAM.getLabel());
        }
        for (ProductDetail productDetail : productList) {
            if (productDetail.getSignEndTime().before(new Date())) {
                return APIResponse.returnFail("活动报名时间超过限制");
            }
        }

        TbOutdoorActivity activity = bizTravelOrderService.queryActivityById(reqSignUser.getId());
        if (null == activity) {
            return APIResponse.returnFail(ErrorEnum.ERROR_PARAM.getId(), ErrorEnum.ERROR_PARAM.getLabel());
        }

        //活动体
        respActivitySignInfo.setId(reqSignUser.getId());
        respActivitySignInfo.setName(activity.getName());
        respActivitySignInfo.setExtendName(activity.getExtendName());
        Gson gson = new Gson();
        MultiMedia multiMedia = gson.fromJson(activity.getMultiMedia(), MultiMedia.class);
        respActivitySignInfo.setMultiple(multiMedia);
        try {
            respActivitySignInfo.setApplyInfo(gson.fromJson(activity.getSignParameter(), ApplyInfoParameter.class));
        }catch (Exception e) {
            logger.debug(e.getMessage());
        }

        //场次
        List<ProductSignInfo> productSignInfos = new ArrayList<>();
        for (ProductDetail activityPreview : productList) {
            ProductSignInfo productSignInfo = new ProductSignInfo();
            productSignInfo.setId(activityPreview.getId());
            productSignInfo.setName(activityPreview.getActivityName());
            if (activityPreview.getStartTime()!=null) {
                productSignInfo.setStartTime(activityPreview.getStartTime().getTime());
            }
            if (activityPreview.getEndTime() != null) {
                productSignInfo.setEndTime(activityPreview.getEndTime().getTime());
            }
            if (activityPreview.getSignStartTime()!=null) {
                productSignInfo.setSignStartTime(activityPreview.getSignStartTime().getTime());
            }
            if (activityPreview.getSignEndTime() != null) {
                productSignInfo.setSignEndTime(activityPreview.getSignEndTime().getTime());
            }
            productSignInfo.setPrice(activityPreview.getPrice());
            productSignInfo.setMemberNum(activityPreview.getLimitNum()-activityPreview.getStorage());
            productSignInfo.setLimitNum(activityPreview.getLimitNum());
            productSignInfo.setDisPlayPrice(activityPreview.getDisplayPrice());
            productSignInfo.setMinNum(activityPreview.getMinNum());

            productSignInfos.add(productSignInfo);
        }
        respActivitySignInfo.setProductInfoList(productSignInfos);
        Discount activityDiscount = new Discount();
        TbOutdoorDiscount tbOutdoorDiscount =  bizTravelOrderService.queryTbOutdoorDiscountByActivityId(reqSignUser.getId());
        if (null != tbOutdoorDiscount) {
            ObjectMapper mapper = new ObjectMapper();
            BeanUtils.copyProperties(tbOutdoorDiscount, activityDiscount);
            List<DiscountParm> list = Lists.newArrayList();
            try {
                list = mapper.readValue(tbOutdoorDiscount.getDiscountParameter(), List.class);
                activityDiscount.setDiscountDetail(list);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        respActivitySignInfo.setActivityDiscount(activityDiscount);
        return APIResponse.returnSuccess(respActivitySignInfo);
    }

    @Override
    public APIResponse userOrder(Integer uid, ReqOrderMsg reqOrderMsg, HttpServletRequest request) throws Exception {
        //校验是是否存在未支付订单
        if (bizTravelOrderService.isExistWaitPayOrder(uid, reqOrderMsg.getProductIds())) {
            return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_DOUBLE.getId(), ErrorEnum.ERROR_ORDER_DOUBLE.getLabel());
        }
        List<ProductDetail> productList = bizTravelOrderService.queryProductDetailByIds(reqOrderMsg.getProductIds()); //校验活动有效性
        if (null == productList || productList.size() == 0) {
            return APIResponse.returnFail(ErrorEnum.ERROR_PARAM.getId(), ErrorEnum.ERROR_PARAM.getLabel());
        }
        TbOutdoorActivity activity = bizTravelOrderService.queryActivityById(reqOrderMsg.getId());
        if (null == activity) {
            return APIResponse.returnFail(ErrorEnum.ERROR_PARAM.getId(), ErrorEnum.ERROR_PARAM.getLabel());
        }
        RespActivityOrderInfo respActivityOrderInfo = new RespActivityOrderInfo();  //封装活动信息
        respActivityOrderInfo.setId(reqOrderMsg.getId());
        respActivityOrderInfo.setType(activity.getType());
        respActivityOrderInfo.setName(activity.getName());
        List<ProductSignInfo> signInfoList = new ArrayList<>();
        double originalPrice = 0.00;
        for (ProductDetail activityPreview : productList) {
            ProductSignInfo productSignInfo = new ProductSignInfo();
            productSignInfo.setId(activityPreview.getId());
            productSignInfo.setName(activityPreview.getActivityName());
            productSignInfo.setStartTime(activityPreview.getStartTime().getTime());
            productSignInfo.setEndTime(activityPreview.getEndTime().getTime());
            productSignInfo.setSignStartTime(activityPreview.getSignStartTime().getTime());
            productSignInfo.setSignEndTime(activityPreview.getSignEndTime().getTime());
            productSignInfo.setPrice(activityPreview.getPrice());
            productSignInfo.setMemberNum(0);
            productSignInfo.setLimitNum(activityPreview.getLimitNum());
            productSignInfo.setExtraMessage(activityPreview.getSignParameter());
            originalPrice += activityPreview.getPrice().doubleValue();
            signInfoList.add(productSignInfo);
        }
        originalPrice = originalPrice * reqOrderMsg.getOrderRquestUserInfoList().size();  //总价
        respActivityOrderInfo.setSignInfoList(signInfoList);
        respActivityOrderInfo.setOrderRequestUserInfos(reqOrderMsg.getOrderRquestUserInfoList());
        respActivityOrderInfo.setPayTypeList(this.queryPayTypeList());

        for(ProductDetail activityPreview : productList){                   ////校验报名时间
            if (!(activityPreview.getSignStartTime().before(new Date()) && activityPreview.getSignEndTime().after(new Date()))) {
                return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_TIME_OUT.getId(), ErrorEnum.ERROR_ORDER_TIME_OUT.getLabel());
            }
        }

        TbOutdoorDiscount activityDiscount = bizTravelOrderService.queryTbOutdoorDiscountByActivityId(reqOrderMsg.getId());
        double discount = this.getActivityDiscount(activityDiscount, reqOrderMsg.getProductIds() != null ? reqOrderMsg.getProductIds().size() : 1);  //获取折扣
        double tempPrice = originalPrice;
        if (discount > 0.0) {
            tempPrice = originalPrice *discount;
        }
        OrderAccumulate orderAccumulate = this.getOrderAccumulate(uid, tempPrice);
        if(null == orderAccumulate) {
            return APIResponse.returnFail(ErrorEnum.ERROR_DUBBO_SERVICE.getId(), ErrorEnum.ERROR_DUBBO_SERVICE.getLabel());
        }
        OrderInfo orderInfo = this.transferOrderInfo(originalPrice, discount, orderAccumulate);
        PrepareOrder prepareOrder = new PrepareOrder();
        prepareOrder.setProductIds(reqOrderMsg.getProductIds());
        prepareOrder.setOrderInfo(orderInfo);
        prepareOrder.setOrderRequestUserInfoList(reqOrderMsg.getOrderRquestUserInfoList());
        prepareOrder.setActivityId(reqOrderMsg.getId());
        if (null != activityDiscount) {
            prepareOrder.setDiscountId(activityDiscount.getId());
        }
        String travelParentOrderNo = this.bookOrder(prepareOrder, uid);  //预下单
        if (null == travelParentOrderNo) {
            return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_LIMIT_OUT.getId(), ErrorEnum.ERROR_ORDER_LIMIT_OUT.getLabel());
        }
        orderInfo.setOrderToken(OrderUtils.generateOrderToken(travelParentOrderNo));
        orderInfo.setOrderNo(travelParentOrderNo);
        respActivityOrderInfo.setOrderInfo(orderInfo);
        respActivityOrderInfo.setExceptionClauseUrl(request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() +
                OutdoorConstants.ACTIVITY_ESCAPE_CLAUSE);
        return APIResponse.returnSuccess(respActivityOrderInfo);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, timeout=10, rollbackFor = Exception.class)
    public APIResponse<?> confirmOrder(Integer uid, ReqOrderConfirmMsg reqOrderConfirmMsg, HttpServletRequest request) {
        String orderNo = reqOrderConfirmMsg.getOrderNo();
        //校验是否重复支付
        TbOutdoorOrder outdoorOrder = bizTravelOrderService.queryOutDoorOrderByOrderNo(orderNo);

        //校验订单安全
        if(!OrderUtils.validateOrderToken(reqOrderConfirmMsg.getOrderNo(), reqOrderConfirmMsg.getOrderToken())) {
            return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_ILLEGAL.getId(), ErrorEnum.ERROR_ORDER_ILLEGAL.getLabel());
        }

        Gson gson = new Gson();
        List<Integer> ids = gson.fromJson(outdoorOrder.getProducts(), new TypeToken<List<Integer>>() {}.getType());
        List<TbOutdoorProduct> productPreviewList = bizTravelOrderService.queryProductByIds(ids);
        if (null == productPreviewList || productPreviewList.size() == 0) {
            return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_ILLEGAL.getId(), ErrorEnum.ERROR_ORDER_ILLEGAL.getLabel());
        }

        //校验报名时间
        for(TbOutdoorProduct tbOutdoorProduct : productPreviewList){
            if (!(tbOutdoorProduct.getSignStartTime().before(new Date()) && tbOutdoorProduct.getSignEndTime().after(new Date()))) {
                return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_TIME_OUT.getId(), ErrorEnum.ERROR_ORDER_TIME_OUT.getLabel());
            }
        }
        //校验订单是否超时
        if (outdoorOrder.getDeadTime().getTime() <= System.currentTimeMillis()) {
            return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_DEADTIME_OUT.getId(), ErrorEnum.ERROR_ORDER_DEADTIME_OUT.getLabel());
        }

        TbOutdoorActivity activity = bizTravelOrderService.queryActivityById(outdoorOrder.getActivityId());

        //刷新户外订单状态 为支付中,订单状态改为未确认
        TbOutdoorOrder order = new TbOutdoorOrder();
        order.setId(outdoorOrder.getId());
        order.setOrderDisplayStatus(OutdoorConstants.APP_TRAVEL_ORDER_WAIT_PAY); // 设置支付中
        order.setPayWait(OutdoorConstants.TRAVEL_ORDER_PAYING);  //设置为支付中
        order.setOrderStatus(OutdoorConstants.TRAVEL_ORDER_NOT_SURE);  //未确认
        order.setPayTime(new Date());
        order.setSrcId(reqOrderConfirmMsg.getPayId());
        int accumulate = outdoorOrder.getAccumulate();
        double accumulateAmount = outdoorOrder.getAccumulateAmount().doubleValue();
        if (!reqOrderConfirmMsg.isUseAccumulate()) {
            accumulate = 0;
            accumulateAmount = 0.00;
            order.setAccumulate(accumulate);
            order.setAccumulateAmount(new BigDecimal(accumulateAmount));
        }
        double payAmount = new BigDecimal(outdoorOrder.getOrderAmount().doubleValue() - outdoorOrder.getDiscountAmount().doubleValue() - accumulateAmount).setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
        order.setPayAmount(new BigDecimal(payAmount));
        bizTravelOrderService.updateTbOutDoorOrder(order);

        //TODO 下单 所在城市ID 渠道号(待确定), 设置让前端传输下
        APIRequest<ReqOrderSave> reqOrderSaveAPIRequest = new APIRequest<>();
        ReqOrderSave reqOrderSave = new ReqOrderSave();
        reqOrderSave.setSourceSystemId(Constants.TRAVEL_SYSTEM_CODE);
        reqOrderSave.setSourceBusinessId(OutdoorConstants.TRAVEL_ORDER_CODE);
        reqOrderSave.setChannelId(1);
        reqOrderSave.setContactMobile("");
        reqOrderSave.setContactName("");
        reqOrderSave.setMchId(2);
        reqOrderSave.setOrderDescribe(activity.getName());
        reqOrderSave.setOrderURL("");
        reqOrderSave.setPayNote("");
        reqOrderSave.setShowURL("");
        reqOrderSave.setBuyerAccount("");
        reqOrderSave.setEggReceiver("百灵鸟");
        reqOrderSave.setEggInfo(activity.getName()+accumulate);
        reqOrderSave.setUserClientIp(request.getRemoteAddr());


        reqOrderSave.setExtraParam(outdoorOrder.getUserInfoParam());
        reqOrderSave.setOrderAmount(new BigDecimal(outdoorOrder.getOrderAmount().doubleValue() - outdoorOrder.getDiscountAmount().doubleValue()).setScale(2,BigDecimal.ROUND_HALF_UP));
        reqOrderSave.setOutTradeNo(outdoorOrder.getOutdoorOrderNo());
        reqOrderSave.setPayTimeOut(OutdoorConstants.ORDER_DEAD_LINE_TIME);  //分钟
        reqOrderSave.setUid(uid);
        reqOrderSave.setService("service.pay");
        List<ProductDetail> products = bizTravelOrderService.queryProductDetailByIds(gson.<List<Integer>>fromJson(outdoorOrder.getProducts(), new TypeToken<List<Integer>>() {
        }.getType()));
        List<ReqProductDetail> reqProductDetailList = new ArrayList<>();
        for (ProductDetail productDetail : products) {
            ReqProductDetail reqProductDetail = new ReqProductDetail();
            reqProductDetail.setShowURL("");
            reqProductDetail.setPrice(productDetail.getPrice());
            reqProductDetail.setProductDesc(productDetail.getActivityName());
            reqProductDetail.setProductId(productDetail.getId()+"");
            reqProductDetail.setProductName(productDetail.getActivityName());
            reqProductDetail.setProductURL(":");
            reqProductDetail.setQuantity(outdoorOrder.getUserNum());
            reqProductDetailList.add(reqProductDetail);
        }
        reqOrderSave.setProductDetailList(reqProductDetailList);
        List<ReqPayInfo> reqPayInfos = new ArrayList<>();
        if (accumulate>0) { //鸟蛋数目大于0发给订单系统
            ReqPayInfo reqPayInfo = new ReqPayInfo();
            reqPayInfo.setPayId(PayWayEnum.PAY_WAY_FOR_AGES.getPayId());
            reqPayInfo.setAmount(new BigDecimal(accumulate).setScale(0, BigDecimal.ROUND_HALF_UP));
            reqPayInfo.setPayType(PayWayEnum.PAY_WAY_FOR_AGES.getPayType());
            reqPayInfos.add(reqPayInfo);
        }
        ReqPayInfo reqPayInfo = new ReqPayInfo();
        reqPayInfo.setPayId(reqOrderConfirmMsg.getPayId());
        reqPayInfo.setAmount(new BigDecimal(payAmount).setScale(2, BigDecimal.ROUND_HALF_UP));
        reqPayInfo.setPayType(PayWayEnum.getById(reqOrderConfirmMsg.getPayId()).getPayType());
        reqPayInfos.add(reqPayInfo);
        reqOrderSave.setPayInfos(reqPayInfos);
        reqOrderSave.setNotifyURL(payUrl);
        reqOrderSave.setCloseNotifyURL(closeOrderUrl);
        reqOrderSave.setExceptionRefundNotify(exceptionOrderUrl);
        reqOrderSave.setRefundNotifyURL(refundUrl);

        //设置版本号,从header中取出
        reqOrderSave.setVer(request.getHeader("APPVersion"));

        reqOrderSaveAPIRequest.setData(reqOrderSave);
        TbOutdoorOrder orderTemp = new TbOutdoorOrder();
        orderTemp.setId(outdoorOrder.getId());
        APIResponse<RespPreOrder> respPreOrderAPIResponse = orderPayService.submitOrder(reqOrderSaveAPIRequest);
        if (null != respPreOrderAPIResponse && respPreOrderAPIResponse.isRet()) {
            RespPreOrder preOrder = respPreOrderAPIResponse.getData();
            orderTemp.setTradeOrderNo(preOrder.getOrderNo());
            if (bizTravelOrderService.updateTbOutDoorOrder(orderTemp).getTradeOrderNo() != null) {
                return APIResponse.returnSuccess(preOrder);
            }
        }else {
            orderTemp.setPayWait(OutdoorConstants.TRAVEL_ORDER_PAY_WAIT);  //设置为待付中
            orderTemp.setOrderStatus(OutdoorConstants.TRAVEL_ORDER_WAIT);  //待确认
            bizTravelOrderService.updateTbOutDoorOrder(orderTemp);
        }

        //记录订单的状态
        travelAsyncService.initOrderRemindAsync(orderTemp.getUid(), orderTemp.getOutdoorOrderNo());

        logger.error("支付失败,请求参数:{}, 返回参数:{}",gson.toJson(reqOrderSaveAPIRequest), gson.toJson(respPreOrderAPIResponse.getErrmsg()));
        return APIResponse.returnFail(respPreOrderAPIResponse.getErrmsg());
    }

    @Override
    public APIResponse payCallback(MessageExt msg) {
        String msgId = msg.getMsgId();
        byte[] bodyByte = msg.getBody();
        OrderNotifyMsg orderNotifyMsg = (OrderNotifyMsg) ObjectUtil.toObject(bodyByte);
        logger.info("消息:订单支付成功，msgId：{} 用户号：{}，订单号：{} ",msgId , orderNotifyMsg.getUid()+"", orderNotifyMsg.getOutTradeNo());
        this.payCallback(orderNotifyMsg);
        return APIResponse.returnSuccess();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, timeout=10, rollbackFor = Exception.class)
    public void payCallback(OrderNotifyMsg orderNotifyMsg) {
        if(orderNotifyMsg.getResultCode() != null){
            //校验是否重复消费
            TbOutdoorOrder orderTemp = bizTravelOrderService.queryOutDoorOrderByOrderNo(orderNotifyMsg.getOutTradeNo());
            if (orderTemp.getPayNotify().intValue() == OutdoorConstants.IS_DELETE || orderTemp.getRefundNotify().intValue() == OutdoorConstants.IS_DELETE ||
                    orderTemp.getCancelNotify().intValue() == OutdoorConstants.IS_DELETE) {
                return;
            }
            switch (orderNotifyMsg.getResultCode()){
                case OrderNotifyMsg.RESULT_CODE_USER_PAY_SUCCESS:
                    orderTemp.setPayWait(OutdoorConstants.TRAVEL_ORDER_PAY_SUCCESS);
                    orderTemp.setOrderStatus(OutdoorConstants.TRAVEL_ORDER_SURE);
                    orderTemp.setIsClose(OutdoorConstants.DEFAULT_STATUS_BYTE_YES);
                    orderTemp.setPayNotify(OutdoorConstants.IS_DELETE);
                    orderTemp.setOrderDisplayStatus(OutdoorConstants.APP_TRAVEL_ORDER_PAYED); // 设置已付款
                    bizTravelOrderService.updateTbOutDoorOrder(orderTemp);
                    if (null != orderTemp && orderTemp.getId() > 0) {
                        //更新用户报名表
                        Gson gson = new Gson();
                        List<OrderRequestUserInfo> users = gson.fromJson(orderTemp.getUserInfoParam(), new TypeToken<List<OrderRequestUserInfo>>() {}.getType());
                        List<Integer> products = gson.fromJson(orderTemp.getProducts(), new TypeToken<List<Integer>>() {}.getType());
                        Integer activityId = orderTemp.getActivityId();
                        for (Integer productId : products) {
                            for (OrderRequestUserInfo userInfo : users) {
                                TbOutdoorSignUser tbSignUser  = new TbOutdoorSignUser();
                                tbSignUser.setActivityId(activityId);
                                tbSignUser.setProductId(productId);
                                tbSignUser.setOutdoorOrderId(orderTemp.getId());
                                tbSignUser.setOrderUserId(orderTemp.getUid());
                                tbSignUser.setName(userInfo.getContactName());
                                tbSignUser.setMobile(userInfo.getContactMobile());
                                tbSignUser.setIdCard(userInfo.getIdCard());
                                tbSignUser.setIsCancel((byte) 0);
                                bizTravelOrderService.insertTbOutdoorSignUser(tbSignUser);
                            }
                        }
                        //用户支付成功
                        List<ProductDetail> productDetails = bizTravelOrderService.queryProductDetailByIds(products);
                        if (null!=productDetails && productDetails.size() > 0) {
                            ProductDetail productDetail = productDetails.get(0);
                            Map<String , Object> params = new HashMap<>();
                            params.put("orderNo", orderTemp.getOutdoorOrderNo());
                            params.put("orderToken", "BAILINGUP");
                            params.put("payId", 1);
                            params.put("useAccumulate", false);
                            travelMsgService.paySuccessMsg(orderTemp.getUid(), productDetail.getActivityName(), productDetail.getPrice(), productDetail.getStartTime().getTime(), params);
                        }
                    }
                    break;
                //支付失败，进行取消订单处理
                case OrderNotifyMsg.RESULT_CODE_USER_PAY_FAIL:
                    orderTemp.setPayWait(OutdoorConstants.TRAVEL_ORDER_PAY_FAIL);
                    orderTemp.setOrderStatus(OutdoorConstants.TRAVEL_ORDER_SURE);
                    bizTravelOrderService.updateTbOutDoorOrder(orderTemp);
                    break;
            }
        }
    }

    @Override
    public APIResponse<RespPaySuccess> paySuccess(Integer uid, String orderNo, HttpServletRequest request) {

        TbOutdoorOrder order = bizTravelOrderService.queryOutDoorOrderByOrderNo(orderNo);
        order.getActivityId();
        TbOutdoorActivity activity = bizTravelOrderService.queryActivityById(order.getActivityId());
        RespPaySuccess respPaySuccess = new RespPaySuccess();
        RespShareActivity shareActivity = new RespShareActivity();
        shareActivity.setTitle(activity.getName());
        shareActivity.setContent(activity.getExtendName());
        Gson gson = new Gson();
        MultiMedia multiMedia = gson.fromJson(activity.getMultiMedia(), MultiMedia.class);
        if (multiMedia.getType() == 0){
            shareActivity.setImageUrl(multiMedia.getImage().getImageUrl());
        }else if(multiMedia.getType() == 1){
            shareActivity.setImageUrl(multiMedia.getVideo().getImageUrl());
        }
        shareActivity.setShareUrl(request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() +
                OutdoorConstants.ACTIVITY_SHARE_URL+"?activityId="+activity.getId()+"&from=share");
        respPaySuccess.setRespShareActivity(shareActivity);
        respPaySuccess.setActivityId(activity.getId());
        HostMsg hostMsg = new HostMsg();


        TbCommonParameter parameterName = travelBaseService.getTbCommonParameter(OutdoorConstants.TRAVEL_CONFIG_HOST_DEFAULT_NAME);
        TbCommonParameter parameterMobile = travelBaseService.getTbCommonParameter(OutdoorConstants.TRAVEL_CONFIG_HOST_DEFAULT_MOBILE);
        hostMsg.setName(parameterName.getParameterValue());
        hostMsg.setMobile(parameterMobile.getParameterValue());
        respPaySuccess.setHostMsg(hostMsg);
        return APIResponse.returnSuccess(respPaySuccess);
    }

    @Override
    public APIResponse refundCallback(MessageExt msg) {
        String msgId = msg.getMsgId();
        byte[] bodyByte = msg.getBody();
        RefundNotifyMsg refundNotifyMsg = (RefundNotifyMsg) ObjectUtil.toObject(bodyByte);
        this.refundCallback(refundNotifyMsg);
        return APIResponse.returnSuccess();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, timeout=10, rollbackFor = Exception.class)
    public void refundCallback(RefundNotifyMsg refundNotifyMsg) {
        //校验是否重复消费
        TbOutdoorOrder outdoorOrder = bizTravelOrderService.queryOutDoorOrderByOrderNo(refundNotifyMsg.getOutTradeNo());
        if(RefundStatusEnum.SUCCESS.getId() == refundNotifyMsg.getRefundState()) {
            logger.info("消息:订单退款成功：订单系统订单号：{} 退款状态：{}", refundNotifyMsg.getOutTradeNo(), refundNotifyMsg.getRefundState());
            outdoorOrder.setOrderStatus(OutdoorConstants.TRAVEL_ORDER_REFUND);
        }else if(RefundStatusEnum.FAIL.getId() == refundNotifyMsg.getRefundState()){
            logger.info("消息:订单退款失败，订单系统订单号：{} ", refundNotifyMsg.getOutTradeNo());
            outdoorOrder.setOrderStatus(OutdoorConstants.TRAVEL_ORDER_REFUND_FAIL);
        }
        else if (RefundStatusEnum.CHANGE.getId() == refundNotifyMsg.getRefundState()){
            logger.info("消息:订单退款失败,需要人工退款，订单系统订单号：{} ", refundNotifyMsg.getOutTradeNo());
            outdoorOrder.setOrderStatus(OutdoorConstants.TRAVEL_ORDER_REFUND_FAIL);
        }
        else {
            logger.info("消息:订单退款异常，订单系统订单号：{} 退款状态：{}", refundNotifyMsg.getOrderNo(), refundNotifyMsg.getRefundState());
            outdoorOrder.setOrderStatus(OutdoorConstants.TRAVEL_ORDER_REFUND_FAIL);
        }
        outdoorOrder.setRefundNotify(OutdoorConstants.IS_DELETE);
        outdoorOrder.setIsClose(OutdoorConstants.IS_DELETE);
        outdoorOrder.setOrderDisplayStatus(OutdoorConstants.APP_TRAVEL_ORDER_REFUND); // 设置已退款
        bizTravelOrderService.updateTbOutDoorOrder(outdoorOrder);
        if (null != outdoorOrder && outdoorOrder.getId() > 0) {
            /*TbOutdoorSignUser tbSignUser  = new TbOutdoorSignUser();
            tbSignUser.setIsCancel((byte) 1);
            TbOutdoorSignUserExample example = new TbOutdoorSignUserExample();
            TbOutdoorSignUserExample.Criteria criteria = example.createCriteria();
            criteria.andOutdoorOrderIdEqualTo(outdoorOrder.getId());
            int i = tbOutdoorSignUserMapper.updateByExampleSelective(tbSignUser, example);
            if (i > 0) {
                logger.info("取消报名成功 ，订单系统订单号：{}", refundNotifyMsg.getOrderNo());


            }*/
            //消息推送退款成功
            TbOutdoorOrder orderTemp = bizTravelOrderService.queryOutDoorOrderByOrderNo(refundNotifyMsg.getOutTradeNo());
            travelMsgService.refundSuccessMsg(orderTemp.getUid(), orderTemp.getOutdoorOrderNo());

            //记录订单的状态
            travelAsyncService.initOrderRemindAsync(orderTemp.getUid(), orderTemp.getOutdoorOrderNo());
        }
        logger.info("退款回调处理完成 ，订单系统订单号：{}", refundNotifyMsg.getOrderNo());
    }

    @Override
    public void refreshTravelStorage() {
        //5分钟刷新一次,每次处理50个订单(只关闭未支付的订单)
        List<TbOutdoorOrder> expireParenteOutDoorOrder = bizTravelOrderService.queryExpireOrder();
        if (null != expireParenteOutDoorOrder && expireParenteOutDoorOrder.size() > 0) {
            if (OutdoorConstants.HANDDLER_EXPIRE_ORDER < expireParenteOutDoorOrder.size()) {
                expireParenteOutDoorOrder = expireParenteOutDoorOrder.subList(0,OutdoorConstants.HANDDLER_EXPIRE_ORDER );
            }
            for (TbOutdoorOrder outdoorOrder : expireParenteOutDoorOrder) {
                //true不需要和支付中心交互
                this.closeOrder(outdoorOrder.getOutdoorOrderNo(), true);
            }
        }

    }

    @Override
    public void updateExceptionalOrderStatus(String orderNo) {
        TbOutdoorOrder orderTemp = bizTravelOrderService.queryOutDoorOrderByOrderNo(orderNo);
        TbOutdoorOrder order = new TbOutdoorOrder();
        order.setId(orderTemp.getId());
        order.setRefundAmount(orderTemp.getPayAmount());        //异常的话全额退款
        order.setRefundAccumulate(orderTemp.getAccumulate());
        order.setOrderStatus(OutdoorConstants.TRAVEL_ORDER_REFUND_WAIT);    //更新为退款中
        bizTravelOrderService.updateTbOutDoorOrder(order);

        travelMsgService.exceptionOrderMsg(orderTemp.getUid(), orderTemp.getOutdoorOrderNo());  //推送消息
    }

    @Override
    public APIResponse cancelOrder(Integer uid, ReqOrderConfirmMsg reqOrderConfirmMsg) {
        if(!OrderUtils.validateOrderToken(reqOrderConfirmMsg.getOrderNo(), reqOrderConfirmMsg.getOrderToken())) {
            return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_ILLEGAL.getId(), ErrorEnum.ERROR_ORDER_ILLEGAL.getLabel()); //校验订单安全
        }
        if (!this.closeOrder(reqOrderConfirmMsg.getOrderNo(), false)) {
            return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_ILLEGAL.getId(), ErrorEnum.ERROR_ORDER_ILLEGAL.getLabel());
        }
        return APIResponse.returnSuccess();
    }

    @Override
    public PageObj<List<RespOrderListMsg>> orderList(Integer uid, Integer pageNum, Integer pageSize) {
        List<RespOrderListMsg> result = new ArrayList<>();
        int total = bizTravelOrderService.queryOutDoorOrderNumByUid(uid);
        if (total == 0) {
            return PageObj.create(total, pageNum, pageSize, result);
        }
        List<TbOutdoorOrder> list = bizTravelOrderService.queryOutDoorOrderListByUid(uid, pageNum, pageSize);
        if (list.size() ==0 ) {
            return PageObj.create(total, pageNum, pageSize, result);
        }
        Gson gson = new Gson();
        Set<Integer>  set = new HashSet<>();
        for (TbOutdoorOrder order:list) {
            List<Integer> temp = gson.fromJson(order.getProducts(), new TypeToken<List<Integer>>() {
            }.getType());
            set.add(temp.get(0));
        }
        List<ProductDetail> productDetails = bizTravelOrderService.queryProductDetailByIds(new ArrayList<Integer>(set));
        Map<Integer , ProductDetail> map = new HashMap<>();
        Map<Integer , TbOutdoorDestination> outdoorDestinationMap = new HashMap<>();
        for (ProductDetail detail : productDetails) {
            map.put(detail.getId(), detail);
            TbOutdoorActivityDestination temp = bizTravelOrderService.queryTbOutdoorActivityDestinationByActivityId(detail.getActivityId());
            if (temp!=null) {
                outdoorDestinationMap.put(detail.getId(), bizTravelOrderService.queryTbOutdoorDestinationById(temp.getDestinationId()));
            }
        }
        for (TbOutdoorOrder order:list) {
            List<Integer> temp = gson.fromJson(order.getProducts(), new TypeToken<List<Integer>>() {
            }.getType());

            if(null==temp || temp.size()<1 || null==map || null==map.get(temp.get(0))){
                continue;
            }

            RespOrderListMsg respOrderListMsg = new RespOrderListMsg();
            respOrderListMsg.setOrderNo(order.getOutdoorOrderNo());
            respOrderListMsg.setActivityId(order.getActivityId());
            respOrderListMsg.setStartTime(map.get(temp.get(0)).getStartTime().getTime());
            respOrderListMsg.setEndTime(map.get(temp.get(0)).getEndTime().getTime());
            respOrderListMsg.setMultiMedia(gson.fromJson(map.get(temp.get(0)).getMultiMedia(), MultiMedia.class));
            respOrderListMsg.setType(map.get(temp.get(0)).getActivityType().byteValue());
            respOrderListMsg.setName(map.get(temp.get(0)).getActivityName());

            TbOutdoorActivity activity = bizTravelOrderService.queryActivityById(order.getActivityId());
            respOrderListMsg.setType(activity.getType());
            respOrderListMsg.setName(activity.getName());
            
            respOrderListMsg.setPrice(order.getPayAmount());
            if (order.getSrcId()!=null) {
                respOrderListMsg.setDefaultPayId(order.getSrcId().byteValue());
            }
            respOrderListMsg.setOrderToken(OrderUtils.generateOrderToken(order.getOutdoorOrderNo()));

            if (OutdoorConstants.APP_TRAVEL_ORDER_PAYED.equals(order.getOrderDisplayStatus())) {
                respOrderListMsg.setOrderStatus(OutdoorConstants.APP_TRAVEL_ORDER_PAYED);
            }else if (OutdoorConstants.APP_TRAVEL_ORDER_REFUNDING.equals(order.getOrderDisplayStatus()) ||
                    OutdoorConstants.APP_TRAVEL_REFUND_APPLY.equals(order.getOrderDisplayStatus())) {
                respOrderListMsg.setOrderStatus(OutdoorConstants.APP_TRAVEL_ORDER_REFUNDING);
            }else if (OutdoorConstants.APP_TRAVEL_ORDER_REFUND.equals(order.getOrderDisplayStatus())) {
                respOrderListMsg.setOrderStatus(OutdoorConstants.APP_TRAVEL_ORDER_REFUND);
            }else if (OutdoorConstants.APP_TRAVEL_ORDER_WAIT_PAY.equals(order.getOrderDisplayStatus())) {
                respOrderListMsg.setOrderStatus(OutdoorConstants.APP_TRAVEL_ORDER_WAIT_PAY);  //
            }else if (OutdoorConstants.APP_TRAVEL_ORDER_CANCEL.equals(order.getOrderDisplayStatus())){
                respOrderListMsg.setOrderStatus(OutdoorConstants.APP_TRAVEL_ORDER_CANCEL);
            }
            
            if (map.get(temp.get(0)).getActivityType().equals(OutdoorConstants.THEME_ACTIVITY_YES)) {
                if (map.get(temp.get(0)).getStartTime().after(new Date())) {
                    respOrderListMsg.setActivityStatus((byte) 0);
                }else if (map.get(temp.get(0)).getStartTime().before(new Date()) && map.get(temp.get(0)).getEndTime().after(new Date())) {
                    respOrderListMsg.setActivityStatus((byte) 1);
                }else {
                    respOrderListMsg.setActivityStatus((byte) 2);
                }
            }else {
                if (map.get(temp.get(0)).getActivityDelete().equals(OutdoorConstants.IS_DELETE)) {
                    respOrderListMsg.setActivityStatus((byte) 2);
                }else {
                    if (map.get(temp.get(0)).getStartTime().after(new Date())) {
                        respOrderListMsg.setActivityStatus((byte) 0);
                    }else if (map.get(temp.get(0)).getStartTime().before(new Date()) && map.get(temp.get(0)).getEndTime().after(new Date())){
                        respOrderListMsg.setActivityStatus((byte) 1);
                    }else {
                        respOrderListMsg.setActivityStatus((byte) 2);
                    }
                }
            }
            respOrderListMsg.setIsAccess(order.getIsAccess());
            if (null!=outdoorDestinationMap && null!=outdoorDestinationMap.get(temp.get(0))) {
                respOrderListMsg.setDestination(outdoorDestinationMap.get(temp.get(0)).getAddress());
            }
            if (order.getDeadTime().after(new Date())) {
                respOrderListMsg.setOrderTimeLength((order.getDeadTime().getTime() - new Date().getTime()));
            }
            result.add(respOrderListMsg);
        }
        return PageObj.create(total, pageNum, pageSize, result);
    }

    @Override
    public APIResponse<RespOrderDetail> orderDetail(Integer uid, String orderNo) {
        RespOrderDetail respOrderDetail = new RespOrderDetail();
        TbOutdoorOrder tbOutdoorOrder = bizTravelOrderService.queryOutDoorOrderByOrderNo(orderNo);
        // 处理订单状态  ()
        if (OutdoorConstants.APP_TRAVEL_ORDER_PAYED.equals(tbOutdoorOrder.getOrderDisplayStatus())) {
            respOrderDetail.setOrderStatus(OutdoorConstants.APP_TRAVEL_ORDER_PAYED);
        }else if (OutdoorConstants.APP_TRAVEL_ORDER_REFUNDING.equals(tbOutdoorOrder.getOrderDisplayStatus()) ||
                OutdoorConstants.APP_TRAVEL_REFUND_APPLY.equals(tbOutdoorOrder.getOrderDisplayStatus())) {
            respOrderDetail.setOrderStatus(OutdoorConstants.APP_TRAVEL_ORDER_REFUNDING);
        }else if (OutdoorConstants.APP_TRAVEL_ORDER_REFUND.equals(tbOutdoorOrder.getOrderDisplayStatus())) {
            respOrderDetail.setOrderStatus(OutdoorConstants.APP_TRAVEL_ORDER_REFUND);
        }else if (OutdoorConstants.APP_TRAVEL_ORDER_WAIT_PAY.equals(tbOutdoorOrder.getOrderDisplayStatus())) {
            respOrderDetail.setOrderStatus(OutdoorConstants.APP_TRAVEL_ORDER_WAIT_PAY);  //
        }else if (OutdoorConstants.APP_TRAVEL_ORDER_CANCEL.equals(tbOutdoorOrder.getOrderDisplayStatus())){
            respOrderDetail.setOrderStatus(OutdoorConstants.APP_TRAVEL_ORDER_CANCEL);
        }

        TbOutdoorActivity activity = bizTravelOrderService.queryActivityById(tbOutdoorOrder.getActivityId());
        Gson gson = new Gson();
        List<Integer> ids = gson.fromJson(tbOutdoorOrder.getProducts(), new TypeToken<List<Integer>>() {}.getType());
        List<ProductDetail> productPreviewList = bizTravelOrderService.queryProductDetailByIds(ids);  //校验活动有效性
        if (null == productPreviewList || productPreviewList.size() == 0) {
            return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_ILLEGAL.getId(), ErrorEnum.ERROR_ORDER_ILLEGAL.getLabel());
        }
        Set<Integer> activityIdSet = new HashSet<>();
        List<ProductSignInfo> productSignInfos = new ArrayList<>();
        for (ProductDetail activityPreview : productPreviewList) {
            activityIdSet.add(activityPreview.getActivityId());
            ProductSignInfo productSignInfo = new ProductSignInfo();
            productSignInfo.setId(activityPreview.getId());
            productSignInfo.setName(activityPreview.getActivityName());
            productSignInfo.setStartTime(activityPreview.getStartTime().getTime());
            productSignInfo.setEndTime(activityPreview.getEndTime().getTime());
            productSignInfo.setSignStartTime(activityPreview.getSignStartTime().getTime());
            productSignInfo.setSignEndTime(activityPreview.getSignEndTime().getTime());
            productSignInfo.setPrice(activityPreview.getPrice());
            productSignInfo.setMemberNum(activityPreview.getLimitNum()-activityPreview.getStorage());
            productSignInfo.setLimitNum(activityPreview.getLimitNum());
            productSignInfo.setExtraMessage(activityPreview.getSignParameter());
            TbOutdoorActivityDestination temp = bizTravelOrderService.queryTbOutdoorActivityDestinationByActivityId(activityPreview.getActivityId());
            if (temp!=null) {
                productSignInfo.setDestination(bizTravelOrderService.queryTbOutdoorDestinationById(temp.getDestinationId()).getAddress());
            }
            productSignInfo.setAddress(activityPreview.getAddress());
            productSignInfo.setLat(activityPreview.getLat());
            productSignInfo.setLng(activityPreview.getLng());
            if(activityPreview.getIsDelete().intValue() == OutdoorConstants.ACTIVITY_UNDERCARRIAGE.intValue()) {
                productSignInfo.setIsDelete(OutdoorConstants.IS_DELETE);
            }else {
                productSignInfo.setIsDelete(OutdoorConstants.IS_NOT_DELETE);
            }
            productSignInfos.add(productSignInfo);
        }
        respOrderDetail.setId(tbOutdoorOrder.getActivityId());
        respOrderDetail.setSignInfoList(productSignInfos);
        respOrderDetail.setIsAccess(tbOutdoorOrder.getIsAccess());
        respOrderDetail.setName(activity.getName());
        respOrderDetail.setType(activity.getType());
        respOrderDetail.setCreateTime(tbOutdoorOrder.getCreateTime().getTime());
        respOrderDetail.setMultiMedia(gson.fromJson(activity.getMultiMedia(),  MultiMedia.class));

        try{
            respOrderDetail.setOrderRequestUserInfos(gson.<List<OrderRequestUserInfo>>fromJson(tbOutdoorOrder.getUserInfoParam(), new TypeToken<List<OrderRequestUserInfo>>() {
            }.getType()));
        }catch (Exception e) {
            logger.error(ErrorEnum.ERROR_ANALYZ_GJSON_ERROR.getLabel());
        }
        respOrderDetail.setDisplayOrderNo(tbOutdoorOrder.getOutdoorOrderNo());
        respOrderDetail.setMasters(bizTravelOrderService.queryOutdoorMaster(new ArrayList<Integer>(activityIdSet)));
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setDefaultPayId(tbOutdoorOrder.getSrcId().byteValue());
        orderInfo.setOrderNo(tbOutdoorOrder.getOutdoorOrderNo());
        orderInfo.setUseAccumulate(new BigDecimal(tbOutdoorOrder.getAccumulate()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        orderInfo.setUseAccumulateAmount(tbOutdoorOrder.getAccumulateAmount().setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        orderInfo.setOrignalAmount(tbOutdoorOrder.getOrderAmount());
        orderInfo.setDiscountAmount(tbOutdoorOrder.getDiscountAmount());
        orderInfo.setPayAmount(tbOutdoorOrder.getPayAmount());
        orderInfo.setOrderTimeLength((long) 0);
        orderInfo.setOrderToken(OrderUtils.generateOrderToken(orderNo));

        if (tbOutdoorOrder.getDeadTime().after(new Date())) {
            orderInfo.setOrderTimeLength((tbOutdoorOrder.getDeadTime().getTime() - new Date().getTime()));
        }
        respOrderDetail.setOrderInfo(orderInfo);

        //记录订单的状态
        travelAsyncService.updateOrderRemindAsync(tbOutdoorOrder.getUid(), tbOutdoorOrder.getOutdoorOrderNo());

        return APIResponse.returnSuccess(respOrderDetail);
    }

    @Override
    public APIResponse<RespRefundOrderMsg> preRefundOrder(String orderNo) {
        RespRefundOrderMsg respRefundOrderMsg = new RespRefundOrderMsg();
        TbOutdoorOrder tbOutdoorOrder = bizTravelOrderService.queryOutDoorOrderByOrderNo(orderNo);
        Gson gson = new Gson();
        List<Integer> ids = gson.fromJson(tbOutdoorOrder.getProducts(), new TypeToken<List<Integer>>() {}.getType());

        List<ProductDetail> productDetailList = bizTravelOrderService.queryProductDetailByIds(ids);

        if (null == productDetailList && productDetailList.size() < 1) {
            return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_ILLEGAL.getId(), ErrorEnum.ERROR_ORDER_ILLEGAL.getLabel()); //校验订单安全
        }

        Date startTime = productDetailList.get(0).getStartTime();
        for (ProductDetail detail : productDetailList) {  //活动开始无法退款
            if (startTime.before(new Date())) {
                return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_REFUND_TIMEOUT.getId(), ErrorEnum.ERROR_ORDER_REFUND_TIMEOUT.getLabel());
            }
            if (startTime.before(detail.getStartTime())){
                startTime = detail.getStartTime();
            }
        }

        RefundOrderInfo refundOrderInfo = this.getRefundOrderInfo(productDetailList, tbOutdoorOrder);
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setDefaultPayId(tbOutdoorOrder.getSrcId().byteValue());
        orderInfo.setOrderNo(tbOutdoorOrder.getOutdoorOrderNo());
        orderInfo.setUseAccumulate(new BigDecimal(tbOutdoorOrder.getAccumulate()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        orderInfo.setUseAccumulateAmount(tbOutdoorOrder.getAccumulateAmount().setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        orderInfo.setOrignalAmount(tbOutdoorOrder.getOrderAmount());
        orderInfo.setDiscountAmount(tbOutdoorOrder.getDiscountAmount());
        orderInfo.setPayAmount(tbOutdoorOrder.getPayAmount());
        orderInfo.setOrderTimeLength((long) 0);

        respRefundOrderMsg.setOrderInfo(orderInfo);
        respRefundOrderMsg.setRefundInfo(refundOrderInfo);
        TbCommonParameter parameterReasons = travelBaseService.getTbCommonParameter(OutdoorConstants.TRAVEL_CONFIG_REFUND_REASON);
        String[] reasons = parameterReasons.getParameterValue().split("#");
        respRefundOrderMsg.setRefundReasons(Arrays.asList(reasons));
        respRefundOrderMsg.setRefundRules(RefundMsgEnum.getAllLabel());
        respRefundOrderMsg.setRuleType(refundOrderInfo.getRuleType());
        TbCommonParameter parameterMobile = travelBaseService.getTbCommonParameter(OutdoorConstants.TRAVEL_CONFIG_HOST_DEFAULT_MOBILE);
        respRefundOrderMsg.setMobile(parameterMobile.getParameterValue());

        respRefundOrderMsg.setRefundTime(tbOutdoorOrder.getRefundTime());
        respRefundOrderMsg.setStartTime(startTime);
        return APIResponse.returnSuccess(respRefundOrderMsg);

    }

    /**
     * 退款规则的设定,这里暂时只支持退款整个订单
     *
     * */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public APIResponse refundOrder(Integer uid, String orderNo, String reason) throws Exception {
        TbOutdoorOrder tbOutdoorOrder = bizTravelOrderService.queryOutDoorOrderByOrderNo(orderNo);
        if (tbOutdoorOrder.getOrderStatus().intValue() == OutdoorConstants.TRAVEL_ORDER_REFUND_WAIT.intValue()) {
            return APIResponse.returnFail("该订单已处于退款中,请等待金额到账");
        }
        Gson gson = new Gson();
        List<Integer> ids = gson.fromJson(tbOutdoorOrder.getProducts(), new TypeToken<List<Integer>>() {}.getType());

        List<ProductDetail> productDetailList = bizTravelOrderService.queryProductDetailByIds(ids);

        if (null == productDetailList && productDetailList.size() < 1) {
            return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_ILLEGAL.getId(), ErrorEnum.ERROR_ORDER_ILLEGAL.getLabel()); //校验订单安全
        }

        for (ProductDetail detail : productDetailList) {  //活动开始无法退款
            if (new Date().after(detail.getStartTime())) {
                return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_REFUND_TIMEOUT.getId(), ErrorEnum.ERROR_ORDER_REFUND_TIMEOUT.getLabel());
            }
        }

        if (null == tbOutdoorOrder || OutdoorConstants.TRAVEL_ORDER_SURE != tbOutdoorOrder.getOrderStatus() || OutdoorConstants.TRAVEL_ORDER_PAY_SUCCESS != tbOutdoorOrder.getPayWait()) {
            return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_ILLEGAL.getId(), ErrorEnum.ERROR_ORDER_ILLEGAL.getLabel()); //校验订单安全
        }

        RefundOrderInfo refundOrderInfo = this.getRefundOrderInfo(productDetailList, tbOutdoorOrder);
        if (refundOrderInfo.getRefundAccumulateAmount() <= 0 && refundOrderInfo.getRefundOrderAmount().doubleValue() <= 0.00) {
            TbOutdoorOrder outdoorOrderTemp = new TbOutdoorOrder();
            outdoorOrderTemp.setId(tbOutdoorOrder.getId());
            outdoorOrderTemp.setOrderStatus(OutdoorConstants.TRAVEL_ORDER_REFUND);
            outdoorOrderTemp.setOrderDisplayStatus(OutdoorConstants.APP_TRAVEL_ORDER_REFUND); // 设置退款成功
            outdoorOrderTemp.setRefundTime(new Date());
            outdoorOrderTemp.setRefundAmount(new BigDecimal(refundOrderInfo.getRefundOrderAmount()).setScale(2, BigDecimal.ROUND_HALF_UP));
            outdoorOrderTemp.setRefundAccumulate(refundOrderInfo.getRefundAccumulateAmount());
            outdoorOrderTemp.setRefundReason(reason);
            boolean update = true;
            try {
                if (!bizTravelOrderService.cancelSignUserByOrderId(tbOutdoorOrder.getId())) {   //用户还原
                    throw new Exception(ErrorEnum.ERROR_ORDER_REFUND.getLabel());
                }
                if (null == bizTravelOrderService.updateTbOutDoorOrder(outdoorOrderTemp)) {     //订单状态刷新
                    throw new Exception(ErrorEnum.ERROR_ORDER_REFUND.getLabel());
                }
                for (Integer integer : ids) {
                    if (!bizTravelOrderService.recoveryTravelStorage(integer, tbOutdoorOrder.getUserNum())) {  //名额回滚
                        throw new Exception(ErrorEnum.ERROR_ORDER_REFUND.getLabel());
                    }
                }
            }catch (Exception e) {
                update = false;
                logger.error(e.getMessage());
            }finally {
                if(!update) {
                    return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_REFUND.getLabel());
                }

                //发送消息退款成功
                travelMsgService.refundSuccessMsg(uid, tbOutdoorOrder.getOutdoorOrderNo());
                return APIResponse.returnSuccess();
            }
        }else {
            TbOutdoorOrder outdoorOrderTemp = new TbOutdoorOrder();
            outdoorOrderTemp.setId(tbOutdoorOrder.getId());
            outdoorOrderTemp.setOrderStatus(OutdoorConstants.TRAVEL_ORDER_REFUND_WAIT);
            outdoorOrderTemp.setRefundTime(new Date());
            outdoorOrderTemp.setOrderDisplayStatus(OutdoorConstants.APP_TRAVEL_REFUND_APPLY); // 设置退款审核中
            if (refundOrderInfo.getRefundOrderAmount().doubleValue() > 0.00) {
                outdoorOrderTemp.setRefundAmount(new BigDecimal(refundOrderInfo.getRefundOrderAmount()).setScale(2, BigDecimal.ROUND_HALF_UP));
            }
            if (refundOrderInfo.getRefundAccumulateAmount() > 0) {
                outdoorOrderTemp.setRefundAccumulate(refundOrderInfo.getRefundAccumulateAmount());
            }
            outdoorOrderTemp.setRefundReason(reason);

            boolean isFlag = true;
            try{
                bizTravelOrderService.updateTbOutDoorOrder(outdoorOrderTemp);   //更新为退款审核中

                bizTravelOrderService.cancelSignUserByOrderId(tbOutdoorOrder.getId());  //报名取消

                for (Integer integer : ids) {
                    if (!bizTravelOrderService.recoveryTravelStorage(integer, tbOutdoorOrder.getUserNum())) {
                        throw new Exception(ErrorEnum.ERROR_ORDER_REFUND.getLabel());
                    }
                }
            }catch (Exception e) {
                isFlag = false;
                logger.debug("用户发起退款审核失败,原因:{}", e);

            }finally {
                //申请退款消息
                if (isFlag) {
                    Map<String , Object> params = new HashMap<>();
                    params.put("orderNo", tbOutdoorOrder.getOutdoorOrderNo());
                    params.put("orderToken", "BAILINGUP");
                    params.put("payId", 1);
                    params.put("useAccumulate", false);
                    travelMsgService.preRefundMsg(uid, params);
                }
                return APIResponse.returnSuccess();
            }
        }
    }

    @Override
    public APIResponse passRefundOrder(String orderNo) throws Exception {
        TbOutdoorOrder tbOutdoorOrder = bizTravelOrderService.queryOutDoorOrderByOrderNo(orderNo);
        if (tbOutdoorOrder.getOrderDisplayStatus().intValue() != OutdoorConstants.APP_TRAVEL_REFUND_APPLY.intValue()) {
            return APIResponse.returnFail("该订单未处于退款申请状态中");
        }
        Gson gson = new Gson();
        List<Integer> ids = gson.fromJson(tbOutdoorOrder.getProducts(), new TypeToken<List<Integer>>() {}.getType());
        List<ProductDetail> productDetailList = bizTravelOrderService.queryProductDetailByIds(ids);
        APIRequest<ReqOrderRefund> orderRefundAPIRequest = new APIRequest<>();
        ReqOrderRefund reqOrderRefund = new ReqOrderRefund();
        reqOrderRefund.setSourceSystemId(Constants.TRAVEL_SYSTEM_CODE);
        reqOrderRefund.setSourceBusinessId(OutdoorConstants.TRAVEL_ORDER_CODE);
        reqOrderRefund.setOrderNo(tbOutdoorOrder.getTradeOrderNo());
        reqOrderRefund.setReason(tbOutdoorOrder.getRefundReason());
        reqOrderRefund.setUid(tbOutdoorOrder.getUid());
        reqOrderRefund.setNeedAudit(false);
        reqOrderRefund.setOutTradeRefundNo(tbOutdoorOrder.getOutdoorOrderNo());
        List<ReqRefundProduct> reqRefundProducts = new ArrayList<>();
        for (ProductDetail detail : productDetailList) {  //活动开始无法退款
            ReqRefundProduct reqRefundProduct = new ReqRefundProduct();
            reqRefundProduct.setPrice(detail.getPrice());
            reqRefundProduct.setQuantity(tbOutdoorOrder.getUserNum());
            reqRefundProduct.setProductName(detail.getActivityName());
            reqRefundProduct.setProductId(detail.getId()+"");
            reqRefundProducts.add(reqRefundProduct);
        }

        List<ReqRefundPayInfo> reqRefundPayInfoList = new ArrayList<ReqRefundPayInfo>();
        if (tbOutdoorOrder.getRefundAmount().doubleValue() > BigDecimal.ZERO.doubleValue()) {
            ReqRefundPayInfo rmb = new ReqRefundPayInfo();
            rmb.setPayId(tbOutdoorOrder.getSrcId());
            rmb.setRefundAmount(tbOutdoorOrder.getRefundAmount().setScale(2, BigDecimal.ROUND_HALF_UP));
            reqRefundPayInfoList.add(rmb);
        }

        if (tbOutdoorOrder.getRefundAccumulate() > BigDecimal.ZERO.intValue()) {
            ReqRefundPayInfo ages = new ReqRefundPayInfo();
            ages.setPayId(PayWayEnum.PAY_WAY_FOR_AGES.getPayId());
            ages.setRefundAmount(new BigDecimal(tbOutdoorOrder.getRefundAccumulate()).setScale(0, BigDecimal.ROUND_HALF_UP));
            reqRefundPayInfoList.add(ages);
        }
        reqOrderRefund.setReqRefundPayInfos(reqRefundPayInfoList);
        reqOrderRefund.setRefundProductList(reqRefundProducts);
        reqOrderRefund.setRefundNotifyURL(refundUrl);
        orderRefundAPIRequest.setData(reqOrderRefund);
        APIResponse<RefundStatusEnum> response = orderPayService.refundApply(orderRefundAPIRequest);
        if (null == response || !response.isRet()) {
            logger.error("退款失败,开始回滚,请求参数:{}, 返回参数:{}",gson.toJson(orderRefundAPIRequest), gson.toJson(response.getErrmsg()));
            return  APIResponse.returnFail("用户退款申请失败");
        }else {
            TbOutdoorOrder outdoorOrderTemp = new TbOutdoorOrder();
            outdoorOrderTemp.setId(tbOutdoorOrder.getId());
            outdoorOrderTemp.setOrderStatus(OutdoorConstants.TRAVEL_ORDER_REFUND_WAIT);
            outdoorOrderTemp.setOrderDisplayStatus(OutdoorConstants.APP_TRAVEL_ORDER_REFUNDING);
            outdoorOrderTemp.setRefundTime(new Date());
            bizTravelOrderService.updateTbOutDoorOrder(outdoorOrderTemp);
            return  APIResponse.returnSuccess();
        }
    }

    @Override
    public APIResponse refundAllOrder(String orderNo) throws Exception {
        TbOutdoorOrder tbOutdoorOrder = bizTravelOrderService.queryOutDoorOrderByOrderNo(orderNo);
        if (tbOutdoorOrder.getOrderStatus().intValue() != OutdoorConstants.APP_TRAVEL_REFUND_APPLY.intValue()) {
            return APIResponse.returnFail("该订单未处于退款申请状态中");
        }
        Gson gson = new Gson();
        List<Integer> ids = gson.fromJson(tbOutdoorOrder.getProducts(), new TypeToken<List<Integer>>() {}.getType());
        List<ProductDetail> productDetailList = bizTravelOrderService.queryProductDetailByIds(ids);
        APIRequest<ReqOrderRefund> orderRefundAPIRequest = new APIRequest<>();
        ReqOrderRefund reqOrderRefund = new ReqOrderRefund();
        reqOrderRefund.setSourceSystemId(Constants.TRAVEL_SYSTEM_CODE);
        reqOrderRefund.setSourceBusinessId(OutdoorConstants.TRAVEL_ORDER_CODE);
        reqOrderRefund.setOrderNo(tbOutdoorOrder.getTradeOrderNo());
        reqOrderRefund.setReason(tbOutdoorOrder.getRefundReason());
        reqOrderRefund.setUid(tbOutdoorOrder.getUid());
        reqOrderRefund.setNeedAudit(false);
        reqOrderRefund.setOutTradeRefundNo(tbOutdoorOrder.getOutdoorOrderNo());
        List<ReqRefundProduct> reqRefundProducts = new ArrayList<>();
        for (ProductDetail detail : productDetailList) {  //活动开始无法退款
            ReqRefundProduct reqRefundProduct = new ReqRefundProduct();
            reqRefundProduct.setPrice(detail.getPrice());
            reqRefundProduct.setQuantity(tbOutdoorOrder.getUserNum());
            reqRefundProduct.setProductName(detail.getActivityName());
            reqRefundProduct.setProductId(detail.getId()+"");
            reqRefundProducts.add(reqRefundProduct);
        }
        List<ReqRefundPayInfo> reqRefundPayInfoList = new ArrayList<ReqRefundPayInfo>();
        if (tbOutdoorOrder.getPayAmount().doubleValue() > BigDecimal.ZERO.doubleValue()) {
            ReqRefundPayInfo rmb = new ReqRefundPayInfo();
            rmb.setPayId(tbOutdoorOrder.getSrcId());
            rmb.setRefundAmount(tbOutdoorOrder.getRefundAmount().setScale(2, BigDecimal.ROUND_HALF_UP));
            reqRefundPayInfoList.add(rmb);
        }
        if (tbOutdoorOrder.getAccumulateAmount().doubleValue() > BigDecimal.ZERO.doubleValue()) {
            ReqRefundPayInfo ages = new ReqRefundPayInfo();
            ages.setPayId(PayWayEnum.PAY_WAY_FOR_AGES.getPayId());
            ages.setRefundAmount(tbOutdoorOrder.getAccumulateAmount().setScale(2, BigDecimal.ROUND_HALF_UP));
            reqRefundPayInfoList.add(ages);
        }
        reqOrderRefund.setReqRefundPayInfos(reqRefundPayInfoList);
        reqOrderRefund.setRefundProductList(reqRefundProducts);
        reqOrderRefund.setRefundNotifyURL(refundUrl);
        orderRefundAPIRequest.setData(reqOrderRefund);
        APIResponse<RefundStatusEnum> response = orderPayService.refundApply(orderRefundAPIRequest);
        if (null == response || !response.isRet()) {
            logger.error("退款失败,开始回滚,请求参数:{}, 返回参数:{}",gson.toJson(orderRefundAPIRequest), gson.toJson(response.getErrmsg()));
            return  APIResponse.returnFail("用户退款申请失败");
        }else {
            TbOutdoorOrder outdoorOrderTemp = new TbOutdoorOrder();
            outdoorOrderTemp.setId(tbOutdoorOrder.getId());
            outdoorOrderTemp.setRefundReason("内部全额退款");
            outdoorOrderTemp.setRefundTime(new Date());
            outdoorOrderTemp.setRefundAmount(tbOutdoorOrder.getPayAmount());
            outdoorOrderTemp.setRefundAccumulate(tbOutdoorOrder.getAccumulate());
            outdoorOrderTemp.setOrderStatus(OutdoorConstants.TRAVEL_ORDER_REFUND_WAIT);
            outdoorOrderTemp.setOrderDisplayStatus(OutdoorConstants.APP_TRAVEL_ORDER_REFUNDING);
            outdoorOrderTemp.setRefundTime(new Date());
            bizTravelOrderService.updateTbOutDoorOrder(outdoorOrderTemp);
            return  APIResponse.returnSuccess();
        }
    }


    @Override
    public APIResponse access(Integer uid, ReqAccess reqAccess) {
        Integer activityId = reqAccess.getActivityId();
        TbOutdoorOrder tbOutdoorOrder = bizTravelOrderService.queryOutDoorOrderByOrderNo(reqAccess.getOrderNo());
        if (null == tbOutdoorOrder ) {
            return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_ILLEGAL.getId(), ErrorEnum.ERROR_ORDER_ILLEGAL.getLabel()); //校验订单安全
        }
        if (tbOutdoorOrder.getIsAccess() == OutdoorConstants.IS_DELETE) {
            return APIResponse.returnFail("无法再次评价");
        }
        if (OutdoorConstants.TRAVEL_ORDER_SURE.equals(tbOutdoorOrder.getOrderStatus())  && OutdoorConstants.TRAVEL_ORDER_PAY_SUCCESS.equals(tbOutdoorOrder.getPayWait()) && uid.equals(tbOutdoorOrder.getUid()) && activityId.equals(tbOutdoorOrder.getActivityId())) {
            Gson gson = new Gson();
            List<Integer> ids = gson.fromJson(tbOutdoorOrder.getProducts(), new TypeToken<List<Integer>>() {}.getType());
            List<TbOutdoorProduct> products = bizTravelOrderService.queryProductByIds(ids);
            if (null == products || products.size() < 1) {
                return APIResponse.returnFail("参数不合法");
            }
            for (TbOutdoorProduct product : products) {
                if (product.getEndTime().after(new Date())) {
                    return APIResponse.returnFail("活动还未结束,无法评价");
                }
            }
            ReqCommentParam reqCommentParam = new ReqCommentParam();
            reqCommentParam.setSystemCode(UserCenterConstants.SystemCode.SYSTEM_OUTDOOR);
            reqCommentParam.setBusinessCode(UserCenterConstants.BusinessCode.BUSINESS_OUTDOOR_CM);
            reqCommentParam.setCommentType(Constants.USER_COMMENT_TYPE);
            reqCommentParam.setBusinessId(activityId);
            reqCommentParam.setFromUserId(uid);
            reqCommentParam.setCommentContent(reqAccess.getContent());
            reqCommentParam.setScore(reqAccess.getScore());
            if (!commentServiceFacade.commentAdd(reqCommentParam).isRet()) {
                return APIResponse.returnFail("调用评价服务失败!!!!");
            }
            ReqUserAccumulateModify req = new ReqUserAccumulateModify();
            req.setSystemCode(Constants.TRAVEL_SYSTEM_CODE);
            req.setBusinessCode(OutdoorConstants.TRAVEL_ACCESS_CODE);
            req.setUid(uid);
            req.setAssetsType(AssetsType.ASSETS_SHELL.getId().byteValue());
            req.setReceiver("户外评价");
            req.setPayReceive(AssetsPayReceive.SYSTEM.getName());
            APIRequest apiRequest = new APIRequest();
            apiRequest.setData(req);
            APIResponse<RespUserAccumulateModify> apiResponse = userAssetsService.modifyAccumulate(apiRequest);
            Eggshell eggshell = new Eggshell();
            eggshell.setCurrentTime(new Date().getTime());
            if (null != apiResponse && apiResponse.isRet()) {
                RespUserAccumulateModify respUserAccumulateModify = apiResponse.getData();
                eggshell.setEggshells(respUserAccumulateModify.getAccumulate().doubleValue());

                //修改状态
                TbOutdoorOrder order = new TbOutdoorOrder();
                order.setId(tbOutdoorOrder.getId());
                order.setIsAccess(OutdoorConstants.IS_DELETE);
                bizTravelOrderService.updateTbOutDoorOrder(order);
            }
            return APIResponse.returnSuccess(eggshell);
        }else {
            return APIResponse.returnFail(ErrorEnum.ERROR_ORDER_ILLEGAL.getId(), ErrorEnum.ERROR_ORDER_ILLEGAL.getLabel()); //校验订单安全
        }

    }

    @Override
    public boolean closeOrderCallback(String parentOrderNo) {
        TbOutdoorOrder outDoorOrder = bizTravelOrderService.queryOutDoorOrderByOrderNo(parentOrderNo);
        if (outDoorOrder.getCancelNotify().intValue() == OutdoorConstants.IS_DELETE || outDoorOrder.getPayNotify().intValue() == OutdoorConstants.IS_DELETE
                || outDoorOrder.getRefundNotify().intValue() == OutdoorConstants.IS_DELETE) {
            return false;
        }
        return this.closeOrder(parentOrderNo, true);
    }

    /**
     *  订单取消,涉及到到订单 outdoorOrder 的订单关闭    order订单状态设置为已取消     库存自动增加个数  鸟蛋恢复
     *
     *  @param parentOrderNo 父订单号
     *  @return boolean
     * */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean closeOrder(String parentOrderNo, boolean isCallback) {
        TbOutdoorOrder outDoorOrder = bizTravelOrderService.queryOutDoorOrderByOrderNo(parentOrderNo);
        if (null == outDoorOrder) {
            logger.debug(ErrorEnum.ERROR_ORDER_ILLEGAL.getLabel());
            return false;
        }

        //订单处于支付直接调起订单取消  (订单系统自动调起我这边,这里不需要自己设置) 只有不处于回调和没有和支付系统交互的订单,isCallback = true
        if (!isCallback) {
            if (outDoorOrder.getPayWait().equals(OutdoorConstants.TRAVEL_ORDER_PAYING) && null != outDoorOrder.getTradeOrderNo()) {
                APIRequest<ReqOrderCancel> orderCancel = new APIRequest<>();
                ReqOrderCancel reqOrderCancel = new ReqOrderCancel();
                reqOrderCancel.setSourceSystemId(Constants.TRAVEL_SYSTEM_CODE);
                reqOrderCancel.setOrderNo(outDoorOrder.getTradeOrderNo());
                reqOrderCancel.setOutTradeNo(outDoorOrder.getOutdoorOrderNo());
                reqOrderCancel.setCancelReason("订单超时");
                reqOrderCancel.setUid(outDoorOrder.getUid());
                orderCancel.setData(reqOrderCancel);
                try{
                    orderPayService.orderCancel(orderCancel);
                }catch (Exception e) {
                    logger.error("订单取消失败,业务订单id:{},订单系统订单id:{},原因:{}", outDoorOrder.getOutdoorOrderNo(),  outDoorOrder.getTradeOrderNo(), e);
                }
            }
        }

        //关闭业务订单
        TbOutdoorOrder outDoorOrderTemp = new TbOutdoorOrder();
        outDoorOrderTemp.setId(outDoorOrder.getId());
        outDoorOrderTemp.setCancelNotify(OutdoorConstants.IS_DELETE);
        outDoorOrderTemp.setIsClose(OutdoorConstants.DEFAULT_STATUS_BYTE_YES);
        outDoorOrderTemp.setOrderDisplayStatus(OutdoorConstants.APP_TRAVEL_ORDER_CANCEL);       //设置为取消状态
        bizTravelOrderService.updateTbOutDoorOrder(outDoorOrderTemp);

        //取消活动模块订单
        Gson gson = new Gson();
        List<Integer> productIds = gson.fromJson(outDoorOrder.getProducts(), new TypeToken<List<Integer>>() {}.getType());
        if (null == productIds || productIds.size() < 1) {
            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("订单下没有场次,订单:{},原因:{}", outDoorOrder.getOutdoorOrderNo(), e);
            }
            return false;
        }

        //回滚库存
        int product = 0;
        try{
            for (Integer integer : productIds) {
                product = integer;
                bizTravelOrderService.recoveryTravelStorage(integer, outDoorOrder.getUserNum());
            }
        }catch (Exception e) {
            logger.error("订单对应的场次人数回滚失败, 场次:{}, 订单:{}", product,  outDoorOrder.getOutdoorOrderNo(), e);
        }
        return true;
    }

    @Override
    public List<PayType> queryPayTypeList() {
        List<PayType> result = new ArrayList<>();
        ReqSysPayInfo reqSysPayInfo = new ReqSysPayInfo();
        reqSysPayInfo.setSourceBusinessId(Constants.TRAVEL_SYSTEM_CODE);
        reqSysPayInfo.setSourceSystemId(OutdoorConstants.TRAVEL_ORDER_CODE);
        APIResponse<List<RespPayInfo>> listAPIResponse = this.orderPayService.selectEnablePayInfos(reqSysPayInfo);
        if (null != listAPIResponse && listAPIResponse.isRet() && null != listAPIResponse.getData()) {
            for (RespPayInfo respPayInfo : listAPIResponse.getData()) {
                PayType payType = new PayType();
                BeanUtils.copyProperties(respPayInfo, payType);
                result.add(payType);
            }
        }
        return result;
    }

    @Override
    public boolean openPayType(List<Integer> ids) {
        ReqSysPayInfo reqSysPayInfo = new ReqSysPayInfo();
        reqSysPayInfo.setPayIds(ids);
        reqSysPayInfo.setSourceBusinessId(Constants.TRAVEL_SYSTEM_CODE);
        reqSysPayInfo.setSourceSystemId(OutdoorConstants.TRAVEL_ORDER_CODE);
        APIResponse<List<RespPayInfo>> result = orderPayService.applyEnablePayInfos(reqSysPayInfo);
        return null != result && result.isRet();
    }

    /**
     * 预下单
     *
     * @param uid
     * @param prepareOrder
     *
     * @return int
     * */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public String bookOrder(PrepareOrder prepareOrder, Integer uid) throws Exception {
        Gson gson = new Gson();
        List<Integer> productIds = prepareOrder.getProductIds();
        List<OrderRequestUserInfo> userInfos = prepareOrder.getOrderRequestUserInfoList();
        OrderInfo orderInfo = prepareOrder.getOrderInfo();
        String parentOutdoorOrderNo = OrderUtils.generateOutDoorOrderNo(uid);
        TbOutdoorOrder tbOutdoorOrder = new TbOutdoorOrder();
        tbOutdoorOrder.setOutdoorOrderNo(parentOutdoorOrderNo);
        tbOutdoorOrder.setActivityId(prepareOrder.getActivityId());
        tbOutdoorOrder.setDiscountId(prepareOrder.getDiscountId());
        tbOutdoorOrder.setProducts(gson.toJson(prepareOrder.getProductIds()));
        tbOutdoorOrder.setDeadTime(DateUtils.addTime(new Date(), OutdoorConstants.ORDER_DEAD_LINE_TIME, DateUtils.TIME_TYPE_MINUTE));
        tbOutdoorOrder.setUserInfoParam(gson.toJson(userInfos));
        tbOutdoorOrder.setUserNum(userInfos.size());
        tbOutdoorOrder.setAccumulate(orderInfo.getUseAccumulate().intValue());
        tbOutdoorOrder.setUid(uid);
        tbOutdoorOrder.setOrderAmount(prepareOrder.getOrderInfo().getOrignalAmount());
        tbOutdoorOrder.setOrderTime(new Date());
        tbOutdoorOrder.setDiscountAmount(orderInfo.getDiscountAmount());
        tbOutdoorOrder.setAccumulateAmount(new BigDecimal(orderInfo.getUseAccumulateAmount()));
        tbOutdoorOrder.setOrderDisplayStatus(OutdoorConstants.APP_TRAVEL_ORDER_WAIT_PAY);
        try{
            for (Integer integer: productIds) {
                if (!bizTravelOrderService.updateTravelStorage(integer, userInfos.size()))
                    throw new Exception(ErrorEnum.ERROR_ORDER_LIMIT_OUT.getLabel());    //校验库存
            }

            if (bizTravelOrderService.insertTravelOrder(tbOutdoorOrder).getId() < 1) {
                throw new Exception(ErrorEnum.ERROR_ORDER_UPDATE.getLabel());
            }
        }catch (Exception e) {
            parentOutdoorOrderNo = null;
            logger.debug(ErrorEnum.ERROR_ORDER_UPDATE.getLabel());
            e.printStackTrace();
        }finally {
            return parentOutdoorOrderNo;
        }
    }

    @Override
    public OrderAccumulate getOrderAccumulate(Integer uid, Double originalPrice) {
        APIRequest<ReqRuleDetail> apiRequest = new APIRequest<>();
        ReqRuleDetail reqRuleDetail = new ReqRuleDetail();


        reqRuleDetail.setSystemCode(Constants.TRAVEL_SYSTEM_CODE);
        reqRuleDetail.setBusinessCode(OutdoorConstants.TRAVEL_ORDER_CODE);
        reqRuleDetail.setOrderAmount(new BigDecimal(originalPrice));
        reqRuleDetail.setAssetsType(AssetsType.ASSETS_EGGS.getId().byteValue());
        reqRuleDetail.setUid(uid);
        apiRequest.setData(reqRuleDetail);
        APIResponse<List<RespRuleDetail>> apiResponse = userAssetsService.getUserAccumulateAndRule(apiRequest);
        if (null != apiResponse && apiResponse.isRet()) {
            RespRuleDetail respRuleDetail = apiResponse.getData().get(0);
            OrderAccumulate orderAccumulate = new OrderAccumulate();
            orderAccumulate.setUid(uid);
            orderAccumulate.setUseAccumulate(respRuleDetail.getUseAccumulate().doubleValue());
            orderAccumulate.setAccumulateRate(respRuleDetail.getAccumulateRule());
            orderAccumulate.setTotalAccumulate(respRuleDetail.getAccount().getAccumulate().doubleValue());
            orderAccumulate.setUseRMB(respRuleDetail.getExchangeRMB());
            return orderAccumulate;
        }
        return null;
    }

    /**
     * 1-2日,提前>3天全额退款
     * 1-2日,提前1-3天退款50%
     * 1-2日,提前24小时内,无法退款
     * 3日以上,提前15天全额退款
     * 3日以上,提前7-15天扣除50%
     * 3日以上,提前7天内,无法退款
     *
     * */
    @Override
    public RefundOrderInfo getRefundOrderInfo(List<ProductDetail> productDetails, TbOutdoorOrder tbOutdoorOrder) {


        RefundOrderInfo refundOrderInfo = new RefundOrderInfo();
        double refundAmount = tbOutdoorOrder.getPayAmount().doubleValue();
        int refundAccumulateAmount = tbOutdoorOrder.getAccumulate();
        double discount = 1.00;
        if (productDetails.size() == 1) {         //非季度
            ProductDetail detail = productDetails.get(0);
            long timeTmp = Math.abs(new Date().getTime() - detail.getStartTime().getTime());
            if (detail.getActivityTime() > 2*24) {  //2天以上
                if (timeTmp < 1000 * 60 * 60 * 24 * 7) {
                    discount = RefundMsgEnum.REFUND_TYPE_6.getDiscount();
                    refundOrderInfo.setRuleType(RefundMsgEnum.REFUND_TYPE_6.getId());
                }else if (timeTmp >= 1000 * 60 * 60 * 24 * 7 && timeTmp < 1000 * 60 * 60 * 24 * 15) {
                    discount = RefundMsgEnum.REFUND_TYPE_5.getDiscount();
                    refundOrderInfo.setRuleType(RefundMsgEnum.REFUND_TYPE_5.getId());
                }else {
                    discount = RefundMsgEnum.REFUND_TYPE_4.getDiscount();
                    refundOrderInfo.setRuleType(RefundMsgEnum.REFUND_TYPE_4.getId());
                }
            }else {
                if (timeTmp < 1000 * 60 * 60 * 24 * 1) {
                    discount = RefundMsgEnum.REFUND_TYPE_3.getDiscount();
                    refundOrderInfo.setRuleType(RefundMsgEnum.REFUND_TYPE_3.getId());
                }else if (timeTmp >= 1000 * 60 * 60 * 24 * 1 && timeTmp < 1000 * 60 * 60 * 24 * 3) {
                    discount = RefundMsgEnum.REFUND_TYPE_2.getDiscount();
                    refundOrderInfo.setRuleType(RefundMsgEnum.REFUND_TYPE_2.getId());
                }else {
                    discount = RefundMsgEnum.REFUND_TYPE_1.getDiscount();
                    refundOrderInfo.setRuleType(RefundMsgEnum.REFUND_TYPE_1.getId());
                }
            }
        }else {  //季度
            int totalHour = 0;
            long firstStartTime = Long.MAX_VALUE;
            for (ProductDetail detail : productDetails) {
                totalHour += detail.getActivityTime();
                if (firstStartTime > detail.getStartTime().getTime()) {
                    firstStartTime = detail.getStartTime().getTime();
                }
            }
            long timeTmp = Math.abs(new Date().getTime() - firstStartTime);
            if (totalHour > 2*24) {
                if (timeTmp >= 1000 * 60 * 60 * 24 * 3) {
                    discount = RefundMsgEnum.REFUND_TYPE_7.getDiscount();
                    refundOrderInfo.setRuleType(RefundMsgEnum.REFUND_TYPE_7.getId());
                }else {
                    discount = RefundMsgEnum.REFUND_TYPE_8.getDiscount();
                    refundOrderInfo.setRuleType(RefundMsgEnum.REFUND_TYPE_8.getId());
                }
            }else {
                if (timeTmp >= 1000 * 60 * 60 * 24 * 15) {
                    discount = RefundMsgEnum.REFUND_TYPE_9.getDiscount();
                    refundOrderInfo.setRuleType(RefundMsgEnum.REFUND_TYPE_9.getId());
                }else {
                    discount = RefundMsgEnum.REFUND_TYPE_10.getDiscount();
                    refundOrderInfo.setRuleType(RefundMsgEnum.REFUND_TYPE_10.getId());
                }
            }
        }
        refundAmount = new BigDecimal(refundAmount * discount).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        refundAccumulateAmount = (int)(refundAccumulateAmount * discount);
        refundOrderInfo.setOrderNo(tbOutdoorOrder.getOutdoorOrderNo());
        refundOrderInfo.setRefundOrderAmount(refundAmount);
        refundOrderInfo.setRefundAccumulateAmount(refundAccumulateAmount);
        return refundOrderInfo;
    }

    @Override
    public List<String> remindOrderNoList(Integer uid) {
        return new ArrayList<>(travelCacheService.getOrderRemindFromCache(uid));
    }


    /**
     * 校验父活动是否已经过期,返回false为报名已满
     *
     * */

    private Map<Integer, Boolean> validateSignTime(List<ProductDetail> activityPreviewList){
        Map<Integer, Boolean> res = new HashMap<>();
        //校验时间
        long currentTime = System.currentTimeMillis();
        for (ProductDetail activityPreview : activityPreviewList) {
            if (activityPreview.getSignEndTime() != null && activityPreview.getSignStartTime() != null) {
                if (activityPreview.getSignStartTime().getTime()<= currentTime && activityPreview.getSignEndTime().getTime() > currentTime) {
                    res.put(activityPreview.getId(), true);
                }else {
                    res.put(activityPreview.getId(), false);
                }
            }else {
                res.put(activityPreview.getId(), true);
            }
        }
        return res;
    }

    private Double getActivityDiscount(TbOutdoorDiscount tbOutdoorDiscount, Integer activityNum){
        List<OrderDiscountInfo> discountInfos = new ArrayList<>();
        double discount = 0.0;
        if (null != tbOutdoorDiscount && tbOutdoorDiscount.getDiscountParameter()!=null) {
            try {
                Gson gson = new Gson();
                discountInfos = gson.fromJson(tbOutdoorDiscount.getDiscountParameter(), new TypeToken<List<OrderDiscountInfo>>() {
                }.getType());
            } catch (Exception e) {
                discountInfos = null;
                logger.error(ErrorEnum.ERROR_ANALYZ_GJSON_ERROR.getLabel());
            } finally {
                if (null != discountInfos && discountInfos.size() > 0) {
                    for (OrderDiscountInfo orderDiscountInfo : discountInfos) {
                        if (activityNum == orderDiscountInfo.getActivityNum()) {
                            discount = orderDiscountInfo.getDiscount();
                            break;
                        }
                    }
                }
            }
        }
        return discount;
    }

    private OrderInfo transferOrderInfo(Double originalPrice, Double discount,  OrderAccumulate o){
        originalPrice = new BigDecimal(originalPrice).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        double discountAmount = 0.00;
        if (discount > 0.0) {
            discountAmount =  new BigDecimal(originalPrice * (1-discount)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        }
        double useAccumulate = o.getUseAccumulate();
        double totalAccumulate = o.getTotalAccumulate();
        double rate = Double.valueOf(o.getAccumulateRate());
        double rmb = o.getUseRMB().doubleValue();
        double payAmount = new BigDecimal(originalPrice - discountAmount - rmb).setScale(2,  BigDecimal.ROUND_HALF_UP).doubleValue();
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrignalAmount(new BigDecimal(originalPrice).setScale(2, BigDecimal.ROUND_HALF_UP));
        orderInfo.setDiscountAmount(new BigDecimal(discountAmount).setScale(2, BigDecimal.ROUND_HALF_UP));
        orderInfo.setUseAccumulate(useAccumulate);
        orderInfo.setTotalAccumulate(totalAccumulate);
        orderInfo.setPayAmount(new BigDecimal(payAmount).setScale(2, BigDecimal.ROUND_HALF_UP));
        orderInfo.setDefaultPayId((byte) 1);
        orderInfo.setUseAccumulateAmount(rmb);
        orderInfo.setOrderMsg("ddd");
        orderInfo.setAccumulateRate(rate);
        orderInfo.setOrderTimeLength((long) (OutdoorConstants.ORDER_DEAD_LINE_TIME * 60*1000));
        return orderInfo;
    }


}
